﻿#include "dx_core.h"
#include <comdef.h>

namespace ifire {

const DirectX::XMFLOAT4X4 IDENTITY_4X4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);

DxException::DxException(HRESULT hr, const std::string& functionName,
    const std::string& filename, int lineNumber)
    : ErrorCode(hr)
    , FunctionName(functionName)
    , Filename(filename)
    , LineNumber(lineNumber) {}

std::string DxException::ToString() const {
  // Get the string description of the error code.
  _com_error err(ErrorCode);
  std::string msg = err.ErrorMessage();

  return FunctionName + " failed in " + Filename + "; line " +
         std::to_string(LineNumber) + "; error: " + msg;
}

std::wstring AnsiToWString(const std::string& str) {
  WCHAR buffer[512];
  MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, buffer, 512);
  return std::wstring(buffer);
}

XMVECTOR compute_normal(FXMVECTOR p0, FXMVECTOR p1, FXMVECTOR p2) {
  auto u = p1 - p0;
  auto v = p2 - p0;

  return XMVector3Normalize(XMVector3Cross(u, v));
}

XMMATRIX inverse_transpose(CXMMATRIX m) {
  // 传参的CXMMATRIX需要一个变换
  XMMATRIX a = m;
  // 去掉平移(Translation)的影响
  a.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);

  XMVECTOR det = XMMatrixDeterminant(a);
  return XMMatrixTranspose(XMMatrixInverse(&det, a));
}

XMMATRIX Spherical::GetViewMatrix() const {
  // 将球面坐标置换为笛卡尔坐标
  float sin_phi = sinf(phi);
  float x = radius * sin_phi * cosf(theta);
  float z = radius * sin_phi * sinf(theta);
  float y = radius * cosf(phi);

  // 构建观察矩阵
  XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
  XMVECTOR target = XMVectorZero();
  XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

  return XMMatrixLookAtLH(pos, target, up);
}

} // namespace ifire